package com.xique.door.biz.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageInfo;
import com.xique.common.core.domain.R;
import com.xique.common.core.utils.DateUtils;
import com.xique.common.core.utils.OrikaUtil;
import com.xique.common.core.utils.SecurityUtils;
import com.xique.common.core.utils.StringUtils;
import com.xique.door.bean.request.elevator.ElevatorAddRequest;
import com.xique.door.bean.request.elevator.ElevatorAllListRequest;
import com.xique.door.bean.request.elevator.ElevatorEditRequest;
import com.xique.door.bean.request.elevator.ElevatorListRequest;
import com.xique.door.bean.transfer.ElevatorTransfer;
import com.xique.door.bean.vo.elevator.ElevatorVo;
import com.xique.door.util.RedisUtil;
import com.xique.common.core.web.domain.AjaxResult;
import com.xique.door.bean.domain.*;
import com.xique.door.bean.response.IotApiResponse;
import com.xique.door.bean.response.domain.*;
import com.xique.door.bean.vo.elevator.ElevatorNotify;
import com.xique.door.biz.service.IElevatorBizService;
import com.xique.door.constant.ElevatorConstant;
import com.xique.door.service.*;
import com.xique.system.api.RemoteSystemUserService;
import com.xique.system.api.dto.OperateDTO;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

/**
 * @author shd
 * @create 2021/10/11 13:44
 */
@Service
public class ElevatorBizServiceImpl implements IElevatorBizService {

    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private IIotApiService iotApiService;

    @Autowired
    private IElevatorService elevatorService;

    @Autowired
    private IElevatorReportService elevatorReportService;

    @Autowired
    private IElevatorParamService elevatorParamService;

    @Autowired
    private IElevatorRunService elevatorRunService;

    @Autowired
    private IElevatorFaultService elevatorFaultService;

    @Autowired
    private IElevatorEventService elevatorEventService;

    @Autowired
    private IElevatorFaultListService elevatorFaultListService;

    @Autowired
    private ElevatorTransfer elevatorTransfer;

    @Autowired
    private RemoteSystemUserService remoteSystemUserService;

    @Override
    public AjaxResult getSessionToken() {
        IotApiResponse response = iotApiService.getMd5Token();
        if (ElevatorConstant.ResponseCode.SUCCESS != response.getResponse_code()) {
            return AjaxResult.error(response.getResponse_msg());
        }
        String md5 = response.getResp().toString();
        response = iotApiService.getAccessToken(md5);
        if (ElevatorConstant.ResponseCode.SUCCESS != response.getResponse_code()) {
            return AjaxResult.error(response.getResponse_msg());
        }
        JSONObject resp = JSONObject.parseObject(JSON.toJSONString(response.getResponse_data()));
        String accessToken = resp.get("access_token").toString();
        response = iotApiService.getSessionToken(accessToken);
        if (ElevatorConstant.ResponseCode.SUCCESS != response.getResponse_code()) {
            return AjaxResult.error(response.getResponse_msg());
        }
        String sessionToken = response.getResp().toString();
        redisUtil.set(ElevatorConstant.IotSessionTokenRedisKey, sessionToken, 2 * 60 * 60 - 3);
        return AjaxResult.success("成功", accessToken);
    }

    @Override
    public AjaxResult syncElvInfo(Long elvId) {
        Elevator elevator = elevatorService.selectElevatorById(elvId);
        String imei = elevator.getImeiCode();

        IotApiResponse response = iotApiService.getElvInfo(imei);
        if (ElevatorConstant.ResponseCode.SUCCESS != response.getResponse_code()) {
            return AjaxResult.error(response.getResponse_msg());
        }
        // 记录电梯基础信息到数据库
        ElvInfo elvInfo = JSONObject.parseObject(JSON.toJSONString(response.getResp()), ElvInfo.class);
        Elevator update = new Elevator();
        update.setId(elvId);
        update.setElvType(elvInfo.getElv_type());
        update.setElvYear(null != elvInfo.getElv_year() ? Integer.parseInt(elvInfo.getElv_year()) : null);
        update.setElevatorBrand(elvInfo.getElv_brand());
        update.setElvPhone(elvInfo.getElv_phone());
        update.setGps(elvInfo.getGps());
        update.setFloors(elvInfo.getFloor());
        update.setSpeed(null != elvInfo.getSpeed() ? Double.parseDouble(elvInfo.getSpeed()) : null);
        update.setDisplayFloor(null != elvInfo.getDisplay_floor() ? elvInfo.getDisplay_floor() : "");

        List<ElvInfoServiceList> serviceList = elvInfo.getService_list();
        for (ElvInfoServiceList service : serviceList) {
            if ("2".equals(service.getService_id())) {
                update.setMonitorPlatformService(1);
            }
            if ("3".equals(service.getService_id())) {
                update.setBatteryCarMonitorService(1);
            }
            if ("4".equals(service.getService_id())) {
                update.setApiService(1);
            }
            if ("8".equals(service.getService_id())) {
                update.setPeopleTrappedService(1);
            }
        }

        int count = elevatorService.updateElevator(update);
        if (count <= 0) {
            return AjaxResult.error("同步失败");
        }
        return AjaxResult.success(response.getResp());
    }

    @Async
    @Override
    public void syncAllElvInfo(Long parkId) {
        Elevator search = new Elevator();
        search.setParkId(parkId);
        List<Elevator> elevatorList = elevatorService.selectElevatorList(search);
        List<Long> elvIds = elevatorList.stream().map(Elevator::getId).collect(Collectors.toList());
        for (Long elvId : elvIds) {
            syncElvInfo(elvId);
        }
    }

    @Override
    public AjaxResult syncElvReport(Long elvId) {
        Elevator elevator = elevatorService.selectElevatorById(elvId);
        String imei = elevator.getImeiCode();

        IotApiResponse response = iotApiService.getElvReport(imei);
        if (ElevatorConstant.ResponseCode.SUCCESS != response.getResponse_code()) {
            return AjaxResult.error(response.getResponse_msg());
        }
        // 记录电梯运行统计到数据库
        ElvReport elvReport = JSONObject.parseObject(JSON.toJSONString(response.getResp()), ElvReport.class);

        ElevatorReport report = new ElevatorReport();
        report.setEleId(elvId);
        report.setEventTimes(elvReport.getEvent_times());
        report.setFaultTimes(elvReport.getFault_times());
        report.setRunHour(elvReport.getRun_hour());
        report.setRunTimes(elvReport.getRun_times());
        report.setRunMeter(elvReport.getRun_meter());

        ElevatorReport search = new ElevatorReport();
        search.setEleId(elvId);
        List<ElevatorReport> list = elevatorReportService.selectElevatorReportList(search);
        int count = 0;
        if (CollectionUtils.isEmpty(list)) {
            // 插入新数据
            count = elevatorReportService.insertElevatorReport(report);
        } else {
            // 更新数据
            report.setId(list.get(0).getId());
            count = elevatorReportService.updateElevatorReport(report);
        }

        if (count <= 0) {
            return AjaxResult.error("同步失败");
        }

        return AjaxResult.success(response.getResp());
    }

    @Async
    @Override
    public void syncAllElvReport(Long parkId) {
        Elevator search = new Elevator();
        search.setParkId(parkId);
        List<Elevator> elevatorList = elevatorService.selectElevatorList(search);
        List<Long> elvIds = elevatorList.stream().map(Elevator::getId).collect(Collectors.toList());
        for (Long elvId : elvIds) {
            syncElvReport(elvId);
        }
    }

    @Override
    public AjaxResult syncElvParam(Long elvId) {
        Elevator elevator = elevatorService.selectElevatorById(elvId);
        String imei = elevator.getImeiCode();

        // 1.获取基础信息
        IotApiResponse response = iotApiService.getElevatorParameter(imei);
        if (ElevatorConstant.ResponseCode.SUCCESS != response.getResponse_code()) {
            return AjaxResult.error(response.getResponse_msg());
        }
        // 记录电梯参数到数据库
        Object object = JSONObject.parseObject(JSON.toJSONString(response.getResp())).get("elevator_parameter");
        ElvParam elvParam = JSONObject.parseObject(JSON.toJSONString(object), ElvParam.class);

        if (StringUtils.isNull(elvParam)) {
            return AjaxResult.success();
        }

        ElevatorParam param = new ElevatorParam();
        param.setEleId(elvId);
        param.setCsq(elvParam.getCsq());
        param.setAvgFloor(elvParam.getAvg_floor());
        param.setCloseDoorTime(elvParam.getClose_door_time());
        param.setConnCount(elvParam.getConn_count());
        param.setDoorWidth(elvParam.getDoor_width());
        param.setFirstUseTime(DateUtils.parseDate(elvParam.getFirst_use_time()));
        param.setMaxAcc(elvParam.getMax_acc());
        param.setMaxDec(elvParam.getMax_dec());
        param.setMaxFloor(elvParam.getMax_floor());
        param.setMaxHeight(elvParam.getMax_height());
        param.setOpenDoorTime(elvParam.getOpen_door_time());

        ElevatorParam search = new ElevatorParam();
        search.setEleId(elvId);
        List<ElevatorParam> list = elevatorParamService.selectElevatorParamList(search);
        int count = 0;
        if (CollectionUtils.isEmpty(list)) {
            // 插入新数据
            count = elevatorParamService.insertElevatorParam(param);
        } else {
            // 更新数据
            param.setId(list.get(0).getId());
            count = elevatorParamService.updateElevatorParam(param);
        }

        if (count <= 0) {
            return AjaxResult.error("同步失败");
        }

        return AjaxResult.success(response.getResp());
    }

    @Async
    @Override
    public void syncAllElvParam(Long parkId) {
        Elevator search = new Elevator();
        search.setParkId(parkId);
        List<Elevator> elevatorList = elevatorService.selectElevatorList(search);
        List<Long> elvIds = elevatorList.stream().map(Elevator::getId).collect(Collectors.toList());
        for (Long elvId : elvIds) {
            syncElvParam(elvId);
        }
    }

    @Async
    @Override
    public void syncAllRuntime(Long parkId) {
        Elevator search = new Elevator();
        search.setParkId(parkId);
        List<Elevator> elevatorList = elevatorService.selectElevatorList(search);
        List<Long> elvIds = elevatorList.stream().map(Elevator::getId).collect(Collectors.toList());
        for (Long elvId : elvIds) {
            syncRuntime(elvId);
        }
    }

    @Async
    @Override
    public void syncAllFault(Long parkId) {
        Elevator search = new Elevator();
        search.setParkId(parkId);
        List<Elevator> elevatorList = elevatorService.selectElevatorList(search);
        List<Long> elvIds = elevatorList.stream().map(Elevator::getId).collect(Collectors.toList());
        for (Long elvId : elvIds) {
            syncFault(elvId);
        }
    }

    @Async
    @Override
    public void syncAllEvent(Long parkId) {
        Elevator search = new Elevator();
        search.setParkId(parkId);
        List<Elevator> elevatorList = elevatorService.selectElevatorList(search);
        List<Long> elvIds = elevatorList.stream().map(Elevator::getId).collect(Collectors.toList());
        for (Long elvId : elvIds) {
            syncEvent(elvId);
        }
    }

    @Async
    @Override
    public void syncAllFaultList(Long parkId) {
        Elevator search = new Elevator();
        search.setParkId(parkId);
        List<Elevator> elevatorList = elevatorService.selectElevatorList(search);
        List<Long> elvIds = elevatorList.stream().map(Elevator::getId).collect(Collectors.toList());
        for (Long elvId : elvIds) {
            syncFaultList(elvId);
        }
    }

    @Override
    public AjaxResult syncRuntime(Long elvId) {
        Elevator elevator = elevatorService.selectElevatorById(elvId);
        String imei = elevator.getImeiCode();

        String startTime = "1970-01-01";
        ElevatorRun elevatorRun = elevatorRunService.selectLastElevatorRunByElvId(elvId);
        if (null != elevatorRun) {
            startTime = DateUtils.parseDateToStr("yyyy-MM-dd", elevatorRun.getEndTime());
        }

        IotApiResponse response = iotApiService.getHisRuntime(imei, startTime, DateUtils.parseDateToStr("yyyy-MM-dd", DateUtils.getNextDate(DateUtils.getNowDate(), 1)), 1, 1);
        if (ElevatorConstant.ResponseCode.SUCCESS != response.getResponse_code()) {
            return AjaxResult.error(response.getResponse_msg());
        }

        ElvRunTime runTime = JSONObject.parseObject(JSON.toJSONString(response.getResp()), ElvRunTime.class);
        Integer total = runTime.getTotal_count();
        List<ElevatorRun> elevatorRuns = new ArrayList<>();
        AtomicReference<Long> runFloor = new AtomicReference<>(0L);
        AtomicReference<Long> upTimes = new AtomicReference<>(0L);
        AtomicReference<Double> upHour = new AtomicReference<>(0.0);
        AtomicReference<Long> downTimes = new AtomicReference<>(0L);
        AtomicReference<Double> downHour = new AtomicReference<>(0.0);
        for (int i = 1; i <= total / 1000 + 1; i++) {
            response = iotApiService.getHisRuntime(imei, startTime, DateUtils.parseDateToStr("yyyy-MM-dd", DateUtils.getNextDate(DateUtils.getNowDate(), 1)), i, 1000);
            runTime = JSONObject.parseObject(JSON.toJSONString(response.getResp()), ElvRunTime.class);
            if (null != runTime && CollectionUtils.isNotEmpty(runTime.getRun_infos())) {
                runTime.getRun_infos().forEach(item -> {
                    if (null == elevatorRun || DateUtils.parseDate(item.getEnd_time()).after(elevatorRun.getEndTime())) {
                        ElevatorRun run = new ElevatorRun();
                        run.setEleId(elvId);
                        run.setEndFloor(item.getEnd_floor());
                        run.setEndTime(DateUtils.parseDate(item.getEnd_time()));
                        run.setMeter(item.getMeter());
                        run.setSpeed(item.getSpeed());
                        run.setStartFloor(item.getStart_floor());
                        run.setStartTime(DateUtils.parseDate(item.getStart_time()));
                        run.setUD(item.getU_d());
                        run.setWaitTime(item.getWait_time());

                        elevatorRuns.add(run);

                        if (!"未知楼层".equals(item.getStart_floor()) && !"未知楼层".equals(item.getEnd_floor())) {
                            runFloor.updateAndGet(v -> v + Math.abs(Long.parseLong(item.getEnd_floor()) - Long.parseLong(item.getStart_floor())));
                        }
                        if (StringUtils.isNotNull(item.getU_d()) && 0 == item.getU_d()) {
                            upTimes.updateAndGet(v -> v++);
                            if (StringUtils.isNotNull(item.getStart_time()) && StringUtils.isNotNull(item.getEnd_time())) {
                                upHour.updateAndGet(v -> v + DateUtils.getHouseDiff(DateUtils.dateTime(DateUtils.YYYY_MM_DD_HH_MM_SS, item.getEnd_time()), DateUtils.dateTime(DateUtils.YYYY_MM_DD_HH_MM_SS, item.getStart_time())));
                            }
                        }
                        if (StringUtils.isNotNull(item.getU_d()) && 1 == item.getU_d()) {
                            downTimes.updateAndGet(v -> v++);
                            if (StringUtils.isNotNull(item.getStart_time()) && StringUtils.isNotNull(item.getEnd_time())) {
                                downHour.updateAndGet(v -> v + DateUtils.getHouseDiff(DateUtils.dateTime(DateUtils.YYYY_MM_DD_HH_MM_SS, item.getEnd_time()), DateUtils.dateTime(DateUtils.YYYY_MM_DD_HH_MM_SS, item.getStart_time())));
                            }
                        }
                    }
                });
            }
        }

        int count = elevatorRunService.insertElevatorRuns(elevatorRuns);

        if (count <= 0) {
            return AjaxResult.error("同步失败");
        }

        ElevatorReport report = elevatorReportService.selectElevatorReportByElvId(elvId);
        if (StringUtils.isNotNull(report)) {
            ElevatorReport update = new ElevatorReport();
            update.setId(report.getId());
            update.setRunFloor(report.getRunFloor() + runFloor.get());
            update.setUpTimes(report.getUpTimes() + upTimes.get());
            update.setUpHour(report.getUpHour() + upHour.get());
            update.setDownTimes(report.getDownTimes() + downTimes.get());
            update.setDownHour(report.getDownHour() + downHour.get());
            elevatorReportService.updateElevatorReport(update);
        }

        return AjaxResult.success(response.getResp());
    }

    @Override
    public AjaxResult syncFault(Long elvId) {
        Elevator elevator = elevatorService.selectElevatorById(elvId);
        String imei = elevator.getImeiCode();

        String startTime = "1970-01-01";
        ElevatorFault elevatorFault = elevatorFaultService.selectLastElevatorFaultByElvId(elvId);
        if (null != elevatorFault) {
            startTime = DateUtils.parseDateToStr("yyyy-MM-dd", elevatorFault.getEndDate());
        }

        IotApiResponse response = iotApiService.getHisFault(imei, startTime, DateUtils.parseDateToStr("yyyy-MM-dd", DateUtils.getNextDate(DateUtils.getNowDate(), 1)), 1, 1);
        if (ElevatorConstant.ResponseCode.SUCCESS != response.getResponse_code()) {
            return AjaxResult.error(response.getResponse_msg());
        }

        ElvFault fault = JSONObject.parseObject(JSON.toJSONString(response.getResp()), ElvFault.class);
        Integer total = fault.getTotal_count();
        List<ElevatorFault> elevatorFaults = new ArrayList<>();
        for (int i = 1; i <= total / 1000 + 1; i++) {
            response = iotApiService.getHisFault(imei, startTime, DateUtils.parseDateToStr("yyyy-MM-dd", DateUtils.getNextDate(DateUtils.getNowDate(), 1)), i, 1000);
            fault = JSONObject.parseObject(JSON.toJSONString(response.getResp()), ElvFault.class);
            fault.getFault_infos().forEach(item -> {
                if (null == elevatorFault || DateUtils.parseDate(item.getEnd_date()).after(elevatorFault.getEndDate())) {
                    ElevatorFault dao = new ElevatorFault();
                    dao.setEleId(elvId);
                    dao.setFaultLevel(item.getFault_level());
                    dao.setEndDate(DateUtils.parseDate(item.getEnd_date()));
                    dao.setStartDate(DateUtils.parseDate(item.getStart_date()));
                    dao.setFaultName(item.getFault_name());
                    dao.setFlag(item.getFlag());

                    elevatorFaults.add(dao);
                }
            });
        }

        int count = elevatorFaultService.insertElevatorFaults(elevatorFaults);

        if (count <= 0) {
            return AjaxResult.error("同步失败");
        }

        return AjaxResult.success(response.getResp());
    }

    @Override
    public AjaxResult syncFaultByImei(String faultJson) {

        ElevatorNotify notify = JSONObject.parseObject(faultJson, ElevatorNotify.class);

        Elevator search = new Elevator();
        search.setImeiCode(notify.getImei());
        List<Elevator> list = elevatorService.selectElevatorList(search);

        if (CollectionUtils.isEmpty(list)) {
            return AjaxResult.error("同步失败");
        }

        Long elvId = list.get(0).getId();

        ElevatorFault fault = new ElevatorFault();
        fault.setEleId(elvId);
        fault.setFaultLevel(notify.getFault_level());
        fault.setEndDate(DateUtils.parseDate(notify.getFault_time()));
        fault.setStartDate(DateUtils.parseDate(notify.getFault_time()));
        fault.setFaultName(notify.getFault_message());
        fault.setFlag("A" + notify.getFlag());

        int count = elevatorFaultService.insertElevatorFault(fault);

        if (count <= 0) {
            return AjaxResult.error("同步失败");
        }

        return AjaxResult.success("同步成功");
    }

    @Override
    public AjaxResult syncEvent(Long elvId) {
        Elevator elevator = elevatorService.selectElevatorById(elvId);
        String imei = elevator.getImeiCode();

        String startTime = "1970-01-01";
        ElevatorEvent elevatorEvent = elevatorEventService.selectLastElevatorEventByElvId(elvId);
        if (null != elevatorEvent) {
            startTime = DateUtils.parseDateToStr("yyyy-MM-dd", elevatorEvent.getStartDate());
        }

        IotApiResponse response = iotApiService.getHisEvent(imei, startTime, DateUtils.parseDateToStr("yyyy-MM-dd", DateUtils.getNextDate(DateUtils.getNowDate(), 1)), 1, 1);
        if (ElevatorConstant.ResponseCode.SUCCESS != response.getResponse_code()) {
            return AjaxResult.error(response.getResponse_msg());
        }

        ElvEvent elvEvent = JSONObject.parseObject(JSON.toJSONString(response.getResp()), ElvEvent.class);
        Integer total = elvEvent.getTotal_count();
        List<ElevatorEvent> elevatorEvents = new ArrayList<>();
        AtomicReference<Long> openTimes = new AtomicReference<>(0L);
        AtomicReference<Long> closeTimes = new AtomicReference<>(0L);
        for (int i = 1; i <= total / 1000 + 1; i++) {
            response = iotApiService.getHisEvent(imei, startTime, DateUtils.parseDateToStr("yyyy-MM-dd", DateUtils.getNextDate(DateUtils.getNowDate(), 1)), i, 1000);
            elvEvent = JSONObject.parseObject(JSON.toJSONString(response.getResp()), ElvEvent.class);
            if (null != elvEvent && CollectionUtils.isNotEmpty(elvEvent.getEvent_infos())) {
                elvEvent.getEvent_infos().forEach(item -> {
                    if (null == elevatorEvent || DateUtils.parseDate(item.getStart_date()).after(elevatorEvent.getStartDate())) {
                        ElevatorEvent event = new ElevatorEvent();
                        event.setEleId(elvId);
                        event.setEventLevel(item.getEvent_level());
                        event.setStartDate(DateUtils.parseDate(item.getStart_date()));
                        event.setEventName(item.getEvent_name());
                        event.setFlag(item.getFlag());

                        elevatorEvents.add(event);

                        if ("A103".equals(item.getFlag())) {
                            openTimes.updateAndGet(v -> v++);
                        }
                        if ("A104".equals(item.getFlag())) {
                            closeTimes.updateAndGet(v -> v++);
                        }
                    }
                });
            }
        }

        int count = elevatorEventService.insertElevatorEvents(elevatorEvents);

        if (count <= 0) {
            return AjaxResult.error("同步失败");
        }

        ElevatorParam param = elevatorParamService.selectElevatorParamByElvId(elvId);

        ElevatorReport report = elevatorReportService.selectElevatorReportByElvId(elvId);
        if (StringUtils.isNotNull(report)) {
            ElevatorReport update = new ElevatorReport();
            update.setId(report.getId());
            update.setOpenTimes(report.getOpenTimes() + openTimes.get());
            update.setOpenHour(report.getOpenHour() + openTimes.get() * (null == param ? 0 : param.getOpenDoorTime()) / (60 * 60));
            update.setCloseTimes(report.getCloseTimes() + closeTimes.get());
            update.setCloseHour(report.getCloseHour() + closeTimes.get() * (null == param ? 0 : param.getOpenDoorTime()) / (60 * 60));
            update.setOpenCloseTimes(report.getOpenCloseTimes() + openTimes.get() + closeTimes.get());
            elevatorReportService.updateElevatorReport(update);
        }

        return AjaxResult.success(response.getResp());
    }

    @Override
    public AjaxResult syncFaultList(Long elvId) {
        Elevator elevator = elevatorService.selectElevatorById(elvId);
        String imei = elevator.getImeiCode();

        String startTime = "1970-01-01";
        ElevatorFaultList elevatorFaultList = elevatorFaultListService.selectLastElevatorFaultListByElvId(elvId);
        if (null != elevatorFaultList) {
            startTime = DateUtils.parseDateToStr("yyyy-MM-dd", elevatorFaultList.getFaultTime());
        }

        IotApiResponse response = iotApiService.getFaultList(imei, startTime, DateUtils.parseDateToStr("yyyy-MM-dd", DateUtils.getNextDate(DateUtils.getNowDate(), 1)));
        if (ElevatorConstant.ResponseCode.SUCCESS != response.getResponse_code()) {
            return AjaxResult.error(response.getResponse_msg());
        }

        ElvFaultList elvFaultList = JSONObject.parseObject(JSON.toJSONString(response.getResp()), ElvFaultList.class);
        List<ElevatorFaultList> elevatorFaultLists = new ArrayList<>();
        elvFaultList.getFaults().forEach(item -> {
            if (null == elevatorFaultList || DateUtils.parseDate(item.getFault_time()).after(elevatorFaultList.getFaultTime())) {
                ElevatorFaultList faultList = new ElevatorFaultList();
                faultList.setEleId(elvId);
                faultList.setCompleteTime(DateUtils.parseDate(item.getComplete_time()));
                faultList.setFaultTime(DateUtils.parseDate(item.getFault_time()));
                faultList.setFaultType(item.getFault_type());
                faultList.setManagerName(item.getManager_name());
                faultList.setManagerPhone(item.getManager_phone());

                elevatorFaultLists.add(faultList);
            }
        });

        int count = elevatorFaultListService.insertElevatorFaultLists(elevatorFaultLists);

        if (count <= 0) {
            return AjaxResult.error("同步失败");
        }

        return AjaxResult.success(response.getResp());
    }

    @Override
    public AjaxResult setNotify(String url) {
        IotApiResponse response = iotApiService.setWarningPost(url);
        if (ElevatorConstant.ResponseCode.SUCCESS != response.getResponse_code()) {
            return AjaxResult.error(response.getResponse_msg());
        }
        return AjaxResult.success(response.getResp());
    }

    @Override
    public AjaxResult elevatorDetail(Long elvId) {

        Elevator elevator = elevatorService.selectElevatorById(elvId);
        if (StringUtils.isNull(elevator)) {
            return AjaxResult.error("未找到对应的电梯信息");
        }
        ElevatorVo vo = OrikaUtil.convert(elevator, ElevatorVo.class);

        return AjaxResult.success(vo);
    }

    @Override
    public AjaxResult addElevator(ElevatorAddRequest request) {
        Elevator elevator = OrikaUtil.convert(request, Elevator.class);
        elevator.setParkId(SecurityUtils.getParkId());

        int count = elevatorService.insertElevator(elevator);
        if (count <= 0) {
            return AjaxResult.error("添加失败");
        }
        return AjaxResult.success("添加成功");
    }

    @Override
    public AjaxResult editElevator(ElevatorEditRequest request) {

        Elevator elevator = OrikaUtil.convert(request, Elevator.class);

        int count = elevatorService.updateElevator(elevator);
        if (count <= 0) {
            return AjaxResult.error("编辑失败");
        }
        return AjaxResult.success("编辑成功");
    }

    @Override
    public AjaxResult removeElevator(String ids) {

        if (StringUtils.isEmpty(ids)) {
            return AjaxResult.error("请传入电梯信息");
        }

        int count = elevatorService.deleteElevatorByIds(ids);
        if (count <= 0) {
            return AjaxResult.error("删除失败");
        }
        return AjaxResult.success("删除成功");
    }

    @Override
    public AjaxResult elevatorList(ElevatorListRequest request) {

        Elevator search = OrikaUtil.convert(request, Elevator.class);
        search.setParkId(SecurityUtils.getParkId());

        List<Elevator> list = elevatorService.selectElevatorList(search);
        List<String> userIds = list.stream().filter(e-> StringUtils.isNotEmpty(e.getUpdateBy())).map(e -> e.getUpdateBy()).collect(Collectors.toList());
        if (!userIds.isEmpty()){
            R<List<OperateDTO>> operateList = remoteSystemUserService.getOperateList(StringUtils.join(userIds, ","));
            List<OperateDTO> data = operateList.getData();
            list.forEach(item -> {
                OperateDTO operateDTO = data.stream().filter(e -> String.valueOf(e.getOperateId()).equals(item.getUpdateBy())).findAny().orElse(null);
                if (operateDTO!=null){
                    item.setUpdateBy(operateDTO.getOperateName());
                }
            });
        }
        long total = new PageInfo(list).getTotal();
        List<ElevatorVo> vos = elevatorTransfer.elevatorTransferElevatorVos(list);

        Map<String, Object> map = new HashMap<>(2);
        map.put("total", total);
        map.put("list", vos);

        return AjaxResult.success(map);
    }

    @Override
    public AjaxResult getAllElevatorList(ElevatorAllListRequest request) {

        Elevator search = OrikaUtil.convert(request, Elevator.class);
        search.setParkId(SecurityUtils.getParkId());

        List<Elevator> list = elevatorService.selectElevatorList(search);

        List<ElevatorVo> vos = elevatorTransfer.elevatorTransferElevatorVos(list);

        Map<String, Object> map = new HashMap<>(2);
        map.put("list", vos);

        return AjaxResult.success(map);
    }

    @Override
    public AjaxResult syncEvents(List<Elevator> list) {

        for (Elevator elevator : list) {
            Long elvId = elevator.getId();
            String imei = elevator.getImeiCode();

            String startTime = "1970-01-01";
            ElevatorEvent elevatorEvent = elevatorEventService.selectLastElevatorEventByElvId(elvId);
            if (null != elevatorEvent) {
                startTime = DateUtils.parseDateToStr("yyyy-MM-dd", elevatorEvent.getStartDate());
            }

            IotApiResponse response = iotApiService.getHisEvent(imei, startTime, DateUtils.parseDateToStr("yyyy-MM-dd", DateUtils.getNextDate(DateUtils.getNowDate(), 1)), 1, 1);
            if (ElevatorConstant.ResponseCode.SUCCESS != response.getResponse_code()) {
                continue;
            }

            ElvEvent elvEvent = JSONObject.parseObject(JSON.toJSONString(response.getResp()), ElvEvent.class);
            Integer total = elvEvent.getTotal_count();
            List<ElevatorEvent> elevatorEvents = new ArrayList<>();
            AtomicReference<Long> openTimes = new AtomicReference<>(0L);
            AtomicReference<Long> closeTimes = new AtomicReference<>(0L);
            for (int i = 1; i <= total / 1000 + 1; i++) {
                response = iotApiService.getHisEvent(imei, startTime, DateUtils.parseDateToStr("yyyy-MM-dd", DateUtils.getNextDate(DateUtils.getNowDate(), 1)), i, 1000);
                elvEvent = JSONObject.parseObject(JSON.toJSONString(response.getResp()), ElvEvent.class);
                if (null != elvEvent && CollectionUtils.isNotEmpty(elvEvent.getEvent_infos())) {
                    elvEvent.getEvent_infos().forEach(item -> {
                        if (null == elevatorEvent || DateUtils.parseDate(item.getStart_date()).after(elevatorEvent.getStartDate())) {
                            ElevatorEvent event = new ElevatorEvent();
                            event.setEleId(elvId);
                            event.setEventLevel(item.getEvent_level());
                            event.setStartDate(DateUtils.parseDate(item.getStart_date()));
                            event.setEventName(item.getEvent_name());
                            event.setFlag(item.getFlag());

                            elevatorEvents.add(event);

                            if ("A103".equals(item.getFlag())) {
                                openTimes.updateAndGet(v -> v++);
                            }
                            if ("A104".equals(item.getFlag())) {
                                closeTimes.updateAndGet(v -> v++);
                            }
                        }
                    });
                }
            }

            elevatorEventService.insertElevatorEvents(elevatorEvents);

            ElevatorParam param = elevatorParamService.selectElevatorParamByElvId(elvId);

            ElevatorReport report = elevatorReportService.selectElevatorReportByElvId(elvId);
            if (StringUtils.isNotNull(report)) {
                ElevatorReport update = new ElevatorReport();
                update.setId(report.getId());
                update.setOpenTimes(report.getOpenTimes() + openTimes.get());
                update.setOpenHour(report.getOpenHour() + openTimes.get() * (null == param ? 0 : param.getOpenDoorTime()) / (60 * 60));
                update.setCloseTimes(report.getCloseTimes() + closeTimes.get());
                update.setCloseHour(report.getCloseHour() + closeTimes.get() * (null == param ? 0 : param.getOpenDoorTime()) / (60 * 60));
                update.setOpenCloseTimes(report.getOpenCloseTimes() + openTimes.get() + closeTimes.get());
                elevatorReportService.updateElevatorReport(update);
            }
        }
        return AjaxResult.success();
    }

    @Override
    public AjaxResult syncRuns(List<Elevator> list) {

        for (Elevator elevator : list) {

            Long elvId = elevator.getId();
            String imei = elevator.getImeiCode();

            String startTime = "1970-01-01";
            ElevatorRun elevatorRun = elevatorRunService.selectLastElevatorRunByElvId(elvId);
            if (null != elevatorRun) {
                startTime = DateUtils.parseDateToStr("yyyy-MM-dd", elevatorRun.getEndTime());
            }

            IotApiResponse response = iotApiService.getHisRuntime(imei, startTime, DateUtils.parseDateToStr("yyyy-MM-dd", DateUtils.getNextDate(DateUtils.getNowDate(), 1)), 1, 1);
            if (ElevatorConstant.ResponseCode.SUCCESS != response.getResponse_code()) {
                continue;
            }

            ElvRunTime runTime = JSONObject.parseObject(JSON.toJSONString(response.getResp()), ElvRunTime.class);
            Integer total = runTime.getTotal_count();
            List<ElevatorRun> elevatorRuns = new ArrayList<>();
            AtomicReference<Long> runFloor = new AtomicReference<>(0L);
            AtomicReference<Long> upTimes = new AtomicReference<>(0L);
            AtomicReference<Double> upHour = new AtomicReference<>(0.0);
            AtomicReference<Long> downTimes = new AtomicReference<>(0L);
            AtomicReference<Double> downHour = new AtomicReference<>(0.0);
            for (int i = 1; i <= total / 1000 + 1; i++) {
                response = iotApiService.getHisRuntime(imei, startTime, DateUtils.parseDateToStr("yyyy-MM-dd", DateUtils.getNextDate(DateUtils.getNowDate(), 1)), i, 1000);
                runTime = JSONObject.parseObject(JSON.toJSONString(response.getResp()), ElvRunTime.class);
                if (null != runTime && CollectionUtils.isNotEmpty(runTime.getRun_infos())) {
                    runTime.getRun_infos().forEach(item -> {
                        if (null == elevatorRun || DateUtils.parseDate(item.getEnd_time()).after(elevatorRun.getEndTime())) {
                            ElevatorRun run = new ElevatorRun();
                            run.setEleId(elvId);
                            run.setEndFloor(item.getEnd_floor());
                            run.setEndTime(DateUtils.parseDate(item.getEnd_time()));
                            run.setMeter(item.getMeter());
                            run.setSpeed(item.getSpeed());
                            run.setStartFloor(item.getStart_floor());
                            run.setStartTime(DateUtils.parseDate(item.getStart_time()));
                            run.setUD(item.getU_d());
                            run.setWaitTime(item.getWait_time());

                            elevatorRuns.add(run);

                            if (!"未知楼层".equals(item.getStart_floor()) && !"未知楼层".equals(item.getEnd_floor())) {
                                runFloor.updateAndGet(v -> v + Math.abs(Long.parseLong(item.getEnd_floor()) - Long.parseLong(item.getStart_floor())));
                            }
                            if (StringUtils.isNotNull(item.getU_d()) && 0 == item.getU_d()) {
                                upTimes.updateAndGet(v -> v++);
                                if (StringUtils.isNotNull(item.getStart_time()) && StringUtils.isNotNull(item.getEnd_time())) {
                                    upHour.updateAndGet(v -> v + DateUtils.getHouseDiff(DateUtils.dateTime(DateUtils.YYYY_MM_DD_HH_MM_SS, item.getEnd_time()), DateUtils.dateTime(DateUtils.YYYY_MM_DD_HH_MM_SS, item.getStart_time())));
                                }
                            }
                            if (StringUtils.isNotNull(item.getU_d()) && 1 == item.getU_d()) {
                                downTimes.updateAndGet(v -> v++);
                                if (StringUtils.isNotNull(item.getStart_time()) && StringUtils.isNotNull(item.getEnd_time())) {
                                    downHour.updateAndGet(v -> v + DateUtils.getHouseDiff(DateUtils.dateTime(DateUtils.YYYY_MM_DD_HH_MM_SS, item.getEnd_time()), DateUtils.dateTime(DateUtils.YYYY_MM_DD_HH_MM_SS, item.getStart_time())));
                                }
                            }
                        }
                    });
                }
            }

            elevatorRunService.insertElevatorRuns(elevatorRuns);

            ElevatorReport report = elevatorReportService.selectElevatorReportByElvId(elvId);
            if (StringUtils.isNotNull(report)) {
                ElevatorReport update = new ElevatorReport();
                update.setId(report.getId());
                update.setRunFloor(report.getRunFloor() + runFloor.get());
                update.setUpTimes(report.getUpTimes() + upTimes.get());
                update.setUpHour(report.getUpHour() + upHour.get());
                update.setDownTimes(report.getDownTimes() + downTimes.get());
                update.setDownHour(report.getDownHour() + downHour.get());
                elevatorReportService.updateElevatorReport(update);
            }
        }
        return AjaxResult.success();
    }

    @Override
    public AjaxResult syncReports(List<Elevator> list) {

        for (Elevator elevator : list) {

            Long elvId = elevator.getId();
            String imei = elevator.getImeiCode();

            IotApiResponse response = iotApiService.getElvReport(imei);
            if (ElevatorConstant.ResponseCode.SUCCESS != response.getResponse_code()) {
                continue;
            }
            // 记录电梯运行统计到数据库
            ElvReport elvReport = JSONObject.parseObject(JSON.toJSONString(response.getResp()), ElvReport.class);

            ElevatorReport report = new ElevatorReport();
            report.setEleId(elvId);
            report.setEventTimes(elvReport.getEvent_times());
            report.setFaultTimes(elvReport.getFault_times());
            report.setRunHour(elvReport.getRun_hour());
            report.setRunTimes(elvReport.getRun_times());
            report.setRunMeter(elvReport.getRun_meter());

            ElevatorReport search = new ElevatorReport();
            search.setEleId(elvId);
            List<ElevatorReport> reportList = elevatorReportService.selectElevatorReportList(search);
            if (CollectionUtils.isEmpty(reportList)) {
                // 插入新数据
                elevatorReportService.insertElevatorReport(report);
            } else {
                // 更新数据
                report.setId(reportList.get(0).getId());
                elevatorReportService.updateElevatorReport(report);
            }
        }

        return AjaxResult.success();
    }
}
